/**
 *******************************************************************************
 *                 Copyright (C) 2017 - 2019  Accumulate Team                
 *                                                                           
 *      Licensed under the Apache License, Version 2.0 (the "License");      
 *      you may not use this file except in compliance with the License.     
 *      You may obtain a copy of the License at                              
 *                 http://www.apache.org/licenses/LICENSE-2.0                
 *                                                                           
 *   Unless required by applicable law or agreed to in writing, software     
 *   distributed under the License is distributed on an "AS IS" BASIS,       
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *******************************************************************************
 * @file       fw_sm.h
 * @author     Accumulate Team
 * @version    1.0.0
 * @date       2017-01-10
 * @brief      framework state machine component head file
 * @par        work platform
 *                 Windows
 * @par        compiler
 *                 GCC
 *******************************************************************************
 * @note
 * 1.20170110    创建文件fw_sm.h
 *******************************************************************************
 */

/**
 * @defgroup framework state machine component
 * @{
 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FRAMEWORK_STATE_MACHINE_H__
#define __FRAMEWORK_STATE_MACHINE_H__

/* Includes ------------------------------------------------------------------*/
#include "sm_config.h"
#include "sm_list.h"

/* Add c++ compatibility -----------------------------------------------------*/
#ifdef __cplusplus
extern "C"
{
#endif

/* Exported macro ------------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief      定义SM相关处理功能
 *******************************************************************************
 */
#define SM_TRAN(me, state)      (((sm_obj_t *)me)->temp = (sm_state_f)(state), \
                                SM_RET_TRAN)
#define SM_HANDLE()                                             (SM_RET_HANDLED)
#define SM_SUPER(me, super) (((sm_obj_t *)me)->super_id = (super), SM_RET_SUPER)
#define SM_BACK(me, state)      (((sm_obj_t *)me)->temp = (sm_state_f)(state), \
                                SM_RET_BACK)
#define SM_EXIT_SUB()                                          (SM_RET_EXIT_SUB)
#define SM_UNHANDLED()                                        (SM_RET_UNHANDLED)
#define SM_WAIT(me, wait)         (((sm_obj_t *)me)->wait = (wait), SM_RET_WAIT)

/**
 *******************************************************************************
 * @brief       定义状态机事件集滤波参数
 *******************************************************************************
 */
#define SM_EVENT_FILTER_AND               0x01                /**< logic and */
#define SM_EVENT_FILTER_OR                0x02                /**< logic or */
#define SM_EVENT_FILTER_CLEAR             0x04                /**< clear flag */

/**
 *******************************************************************************
 * @brief       定义状态表回调返回值
 *******************************************************************************
 */    
#define SM_FSM_TABLE_RET_NONE                       ((sm_fsm_table_ret_t){0, 0})

/**
 *******************************************************************************
 * @brief        定义组件名称
 *******************************************************************************
 */
#define SM_COMPONENT_NAME "sm"

/* Exported types ------------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief        定义状态机事件
 *******************************************************************************
 */
enum SM_EVENT_DEFINE
{
    SM_EMPTY_EVENT = 0,

    SM_CORE_TICK_EVENT,
    SM_INIT_EVENT,
    SM_ENTRY_EVENT,
    SM_EXIT_EVENT,
    SM_TICK_EVENT,
    SM_TIMEOUT_EVENT,

    SM_FSMTABLE_ENTRY_EVENT,
    SM_FSMTABLE_EXIT_EVENT,
    SM_FSMTABLE_TRIGGER_EVENT,

    SM_USER_EVENT_DEFINE,
    
    SM_EVEN_MAX,
};

/**
 *******************************************************************************
 * @brief      定义状态机数据类型
 *******************************************************************************
 */
enum SM_RET_DEF
{
    SM_RET_IGNORED = 0,
    SM_RET_HANDLED,
    SM_RET_UNHANDLED,

    SM_RET_SUPER,
    SM_RET_SUPER_SUB,
    
    SM_RET_WAIT,

    SM_RET_CALL,
    SM_RET_BACK,
    SM_RET_EXIT_SUB,

    SM_RET_AGAIN,

    SM_RET_ENTRY,
    SM_RET_EXIT,

    SM_RET_NULL,

    SM_RET_TRAN,
    SM_RET_TRAN_INIT,
    SM_RET_TRAN_HIST,
};

/**
 *******************************************************************************
 * @brief      定义状态机消息类型
 *******************************************************************************
 */
struct SM_OBJECT;
typedef struct SM_MESSAGE
{
    struct SM_OBJECT *obj;

    //! not used
    uint32_t index;

    enum SM_EVENT_DEFINE sig;

    union
    {
        void *param;
        uint32_t val;
    };
}sm_msg_t;

/**
 *******************************************************************************
 * @brief      定义状态表数据类型
 *******************************************************************************
 */
typedef struct FSM_TABLE
{
    uint32_t cur_state;
    uint32_t in_event;
    uint32_t tran_state;
    uint32_t out_event;
    uint32_t state_mask;

    void *param;
}sm_fsm_table_t;

typedef struct
{
    uint32_t tran_state;
    uint32_t out_event;
}sm_fsm_table_ret_t;

typedef struct
{
    sm_fsm_table_ret_t (*callback)(struct SM_OBJECT*, const struct FSM_TABLE*, sm_msg_t*);

    const sm_fsm_table_t *buffer;
    uint32_t       len;

    uint16_t state;
    uint16_t wait;
}sm_table_handle_t;

/**
 *******************************************************************************
 * @brief      定义状态机定时器数据类型
 *******************************************************************************
 */
typedef struct SM_TIMER
{
    sm_list_t list;

    struct SM_TIMER_ATTRIBUTE
    {
        struct SM_OBJECT *obj;

        uint32_t  trig;

        sm_tick_t tick;

        uint32_t  state : 1;
    } attribute;
}sm_timer_t;

/**
 *******************************************************************************
 * @brief       定义状态机事件集数据结构
 *******************************************************************************
 */
typedef struct SM_EVENT_FLAG
{
    sm_list_t list;

	uint32_t set;

    uint32_t : 32;	
}sm_event_flag_t;

/**
 *******************************************************************************
 * @brief       定义事件滤波器数据结构
 *******************************************************************************
 */
typedef struct SM_FLAG_FILTER
{
    sm_list_t list;

    struct SM_FLAG_FILTER_ATTRIBUTE
    {
        struct SM_OBJECT *obj;

        void *param;

        uint32_t get;
        uint32_t flag : 4;
        uint32_t trig : 14;
    }attribute;
}sm_event_flag_filter_t;

/**
 *******************************************************************************
 * @brief      定义状态机信号数据类型
 *******************************************************************************
 */
typedef struct SM_SIG
{
    sm_list_t list;

    uint32_t owner : 16;
    uint32_t       : 16;
    uint32_t       : 32;
}sm_sig_t;

/**
 *******************************************************************************
 * @brief      定义状态机槽数据类型
 *******************************************************************************
 */
typedef struct SM_SLOT
{
    sm_list_t list;

    union
    {
        struct
        {
            void (*callback)(void *param);
            void *param;
        };
        
        struct
        {
            struct SM_OBJECT *obj;
            uint32_t trig;
        };
    };

    uint32_t is_dynamic       : 1;
    uint32_t is_trig_callback : 1;
    uint32_t is_trig_message  : 1;
}sm_slot_t;

/**
 *******************************************************************************
 * @brief      定义状态机状态类型
 *******************************************************************************
 */
typedef uint8_t (*sm_state_f)(struct SM_OBJECT *me, sm_msg_t *evt);

/**
 *******************************************************************************
 * @brief      FSM 数据结构
 *******************************************************************************
 */
//! FSM处理句柄
typedef struct SM_OBJECT
{
    //! 定义状态机父类
    sm_parent_t parent_class;

    //! 当前状态
    sm_state_f state;
    sm_state_f temp;

    //! 状态机列表
    sm_list_t list;
 
    //! 状态表
    sm_table_handle_t fsm_table;

    //! 状态机ID
    struct SM_OBJECT *super;

    //! 定义状态机属性
    struct
    {
        uint32_t is_dynamic : 1;
        uint32_t is_init    : 1;
    }attribute;

    //! 定义定时器句柄
    sm_timer_t timer;

    //! 定义事件集句柄
    sm_event_flag_t event_flag;
    sm_event_flag_filter_t event_flag_filter;

    sm_list_t event_flag_list;

    //! 定时器列表
    sm_list_t sig_list;
}sm_obj_t;

/**
 *******************************************************************************
 * @brief        定义状态机操作接口
 *******************************************************************************
 */
//! 定义定时器操作接口
struct SM_SELF_TIMER_OPS
{
    void (*init)(void);
    void (*start)(uint16_t evt, sm_tick_t tick);
    void (*stop)(void);
};

//! 定义事件FLAG操作接口
struct SM_SELF_EVENT_FLAG_OPS
{
    void (*init)(void);
    void (*set)(uint32_t evt);
    void (*append)(uint32_t recv, uint32_t flag, sm_obj_t *obj, uint16_t trig);
    void (*append_static)(sm_event_flag_filter_t *filter, uint32_t recv, uint32_t flag, sm_obj_t *obj, uint16_t trig);
    void (*fini)(void);
};

//! 定义信号操作接口
struct SM_SELF_SIGNAL_OPS
{
    void (*init)(sm_sig_t *sig);
    void (*fini)(sm_sig_t *sig);
    void (*emit)(sm_sig_t *sig);

    sm_slot_t* (*connect)(sm_sig_t *sig, void *cb, void *param);
    void (*connect_static)(sm_sig_t *sig, sm_slot_t *slot, void *cb, void *param);

    sm_slot_t* (*connect_event)(sm_sig_t *sig, sm_obj_t *obj, uint16_t trig);
    void (*connect_event_static)(sm_sig_t *sig, sm_slot_t *slot, sm_obj_t *obj, uint16_t trig);

    void (*disconnect)(sm_slot_t *slot);
};

//! 定义SELF操作接口
typedef struct SM_SELF
{
    //! define timer ops
    const struct SM_SELF_TIMER_OPS *timer;

    //! define flag ops
    const struct SM_SELF_EVENT_FLAG_OPS *flag;

    //! define sig ops
    const struct SM_SELF_SIGNAL_OPS *sig;

    //! 状态机对象
    sm_obj_t *obj;
}sm_self_t;

/**
 *******************************************************************************
 * @brief        状态机管理句柄定义
 *******************************************************************************
 */
struct SM_CORE_HANDLE
{
    //! 状态机对象列表
    sm_list_t obj_list;

    //! 定时器列表
    sm_list_t timer_list;
    
    //! 记录上一次tick值
    sm_tick_t last_tick;

    //! 定义当前状态机操作接口
    sm_self_t *self;
};

/* Exported variables --------------------------------------------------------*/

/* Exported functions --------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief        PORT API
 * @note         PUBLIC, 由PORT组件提供
 *******************************************************************************
 */
extern inline sm_tick_t sm_tick_get(void);

extern void sm_msg_post(sm_obj_t *obj, uint32_t sig, void *param);

extern struct SM_CORE_HANDLE *sm_core(void);

extern void sm_parent_init(sm_obj_t *sm, char *name);
extern char *sm_obj_name(sm_obj_t *sm);

/**
 *******************************************************************************
 * @brief       SM TIMER API
 *******************************************************************************
 */
extern void sm_timer_process(struct SM_CORE_HANDLE *handle);

extern void sm_timer_init(sm_timer_t *timer);
extern void sm_timer_start(sm_timer_t *timer, sm_obj_t *obj, uint16_t evt, sm_tick_t tick);
extern void sm_timer_stop(sm_timer_t *timer);

extern void sm_self_timer_init(void);
extern void sm_self_timer_start(uint16_t evt, sm_tick_t tick);
extern void sm_self_timer_stop(void);

/**
 *******************************************************************************
 * @brief       SM EVENT API
 *******************************************************************************
 */
extern void sm_event_flag_init(sm_event_flag_t *evt);
extern void sm_event_flag_send(sm_event_flag_t *evt, uint32_t set);

extern void sm_event_flag_filter_init(sm_event_flag_filter_t *filter);
extern void sm_event_flag_filter_clear(sm_event_flag_t *evt);
extern void sm_event_flag_filter_remove(sm_event_flag_filter_t *filter);
extern void sm_event_flag_filter_append(sm_event_flag_t *evt, 
                                        sm_event_flag_filter_t *filter, 
                                        uint32_t recv, uint32_t flag, 
                                        sm_obj_t *obj, uint32_t trig);

/**
 *******************************************************************************
 * @brief        SM SIG API
 *******************************************************************************
 */
extern void sm_sig_init(sm_sig_t *sig);
extern void sm_sig_fini(sm_sig_t *sig);

extern void sm_sig_emit(sm_sig_t *sig);

extern void      sm_sig_connect_event_static(sm_sig_t *sig, sm_slot_t *slot, 
                                             sm_obj_t *obj, uint16_t trig);

extern sm_slot_t *sm_sig_connect_event(sm_sig_t *sig, sm_obj_t *obj, uint16_t trig);

extern void      sm_sig_connect_callback_static(sm_sig_t *sig, sm_slot_t *slot, void *cb, void *param);
extern sm_slot_t *sm_sig_connect_callback(sm_sig_t *sig, void *cb, void *param);

extern void sm_sig_disconnect(sm_slot_t *slot);

/**
 *******************************************************************************
 * @brief       SM FSM TABLE操作接口
 *******************************************************************************
 */
extern void sm_fsm_table_mnt(const sm_fsm_table_t *table, 
                             uint32_t len,
                             sm_fsm_table_ret_t (*callback)(struct SM_OBJECT*, const struct FSM_TABLE*, sm_msg_t *msg));

extern void sm_fsm_table_unmnt(void);

extern uint8_t sm_fsm_table_process(sm_obj_t *me, sm_msg_t *msg);

/**
 *******************************************************************************
 * @brief        SM CORE API
 *******************************************************************************
 */
extern uint8_t sm_core_init(struct SM_CORE_HANDLE *handle);
extern uint8_t sm_core_process(sm_obj_t *me, sm_msg_t *msg);

extern sm_self_t *sm_self(void);
extern sm_obj_t *sm_self_obj(void);

extern sm_obj_t *sm_obj_find(char *name);
extern void sm_obj_append(sm_obj_t *obj);
extern void sm_obj_remove(sm_obj_t *obj);

extern void sm_obj_init(sm_obj_t *me, char *name, sm_state_f init);
extern sm_obj_t *sm_obj_create(char *name, sm_state_f init);
extern void sm_obj_delete(char *name);

/* Add c++ compatibility------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
	
#endif       /** end include define */

/** @}*/     /** framework state machine component */

/**********************************END OF FILE*********************************/
